package com.lifeverse.service;

import com.lifeverse.entity.PerformanceMetric;
import com.lifeverse.entity.enums.MetricType;
import io.micrometer.core.annotation.Timed;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;

/**
 * 性能基准测试服务
 * 提供自动化性能测试和基准测试功能
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PerformanceBenchmarkService {
    
    private final PerformanceMonitoringService performanceMonitoringService;
    private final MeterRegistry meterRegistry;
    
    /**
     * 基准测试结果
     */
    public static class BenchmarkResult {
        private String testName;
        private LocalDateTime executedAt;
        private Duration totalDuration;
        private long operationsCount;
        private double operationsPerSecond;
        private Duration averageOperationTime;
        private Duration minOperationTime;
        private Duration maxOperationTime;
        private double successRate;
        private Map<String, Object> additionalMetrics;
        
        public BenchmarkResult(String testName) {
            this.testName = testName;
            this.executedAt = LocalDateTime.now();
            this.additionalMetrics = new HashMap<>();
        }
        
        // Getters and Setters
        public String getTestName() { return testName; }
        public void setTestName(String testName) { this.testName = testName; }
        
        public LocalDateTime getExecutedAt() { return executedAt; }
        public void setExecutedAt(LocalDateTime executedAt) { this.executedAt = executedAt; }
        
        public Duration getTotalDuration() { return totalDuration; }
        public void setTotalDuration(Duration totalDuration) { this.totalDuration = totalDuration; }
        
        public long getOperationsCount() { return operationsCount; }
        public void setOperationsCount(long operationsCount) { this.operationsCount = operationsCount; }
        
        public double getOperationsPerSecond() { return operationsPerSecond; }
        public void setOperationsPerSecond(double operationsPerSecond) { this.operationsPerSecond = operationsPerSecond; }
        
        public Duration getAverageOperationTime() { return averageOperationTime; }
        public void setAverageOperationTime(Duration averageOperationTime) { this.averageOperationTime = averageOperationTime; }
        
        public Duration getMinOperationTime() { return minOperationTime; }
        public void setMinOperationTime(Duration minOperationTime) { this.minOperationTime = minOperationTime; }
        
        public Duration getMaxOperationTime() { return maxOperationTime; }
        public void setMaxOperationTime(Duration maxOperationTime) { this.maxOperationTime = maxOperationTime; }
        
        public double getSuccessRate() { return successRate; }
        public void setSuccessRate(double successRate) { this.successRate = successRate; }
        
        public Map<String, Object> getAdditionalMetrics() { return additionalMetrics; }
        public void setAdditionalMetrics(Map<String, Object> additionalMetrics) { this.additionalMetrics = additionalMetrics; }
    }
    
    /**
     * 定时执行基准测试
     */
    @Scheduled(fixedRate = 3600000) // 每小时执行一次
    public void runScheduledBenchmarks() {
        try {
            log.info("开始执行定时基准测试");
            
            // 执行各种基准测试
            runCpuBenchmark();
            runMemoryBenchmark();
            runDatabaseBenchmark();
            runCacheBenchmark();
            runNetworkBenchmark();
            
            log.info("定时基准测试执行完成");
            
        } catch (Exception e) {
            log.error("执行定时基准测试失败", e);
        }
    }
    
    /**
     * CPU 基准测试
     */
    @Timed(value = "benchmark.cpu", description = "CPU benchmark test")
    public BenchmarkResult runCpuBenchmark() {
        BenchmarkResult result = new BenchmarkResult("CPU_BENCHMARK");
        
        Timer.Sample sample = Timer.start(meterRegistry);
        LocalDateTime startTime = LocalDateTime.now();
        
        try {
            int operationsCount = 1000000;
            List<Duration> operationTimes = new ArrayList<>();
            int successCount = 0;
            
            for (int i = 0; i < operationsCount; i++) {
                LocalDateTime opStart = LocalDateTime.now();
                
                try {
                    // CPU 密集型计算
                    double result1 = performCpuIntensiveCalculation();
                    successCount++;
                    
                    Duration opDuration = Duration.between(opStart, LocalDateTime.now());
                    operationTimes.add(opDuration);
                    
                } catch (Exception e) {
                    log.debug("CPU基准测试操作失败: {}", e.getMessage());
                }
            }
            
            Duration totalDuration = Duration.between(startTime, LocalDateTime.now());
            sample.stop(meterRegistry.timer("benchmark.cpu.total"));
            
            // 计算统计信息
            calculateBenchmarkStatistics(result, totalDuration, operationsCount, 
                    successCount, operationTimes);
            
            // 记录性能指标
            recordBenchmarkMetrics("cpu_benchmark", result);
            
            log.info("CPU基准测试完成: 操作数={}, 成功率={:.2f}%, 平均OPS={:.2f}", 
                    operationsCount, result.getSuccessRate(), result.getOperationsPerSecond());
            
        } catch (Exception e) {
            log.error("CPU基准测试失败", e);
            sample.stop(meterRegistry.timer("benchmark.cpu.error"));
        }
        
        return result;
    }
    
    /**
     * 内存基准测试
     */
    @Timed(value = "benchmark.memory", description = "Memory benchmark test")
    public BenchmarkResult runMemoryBenchmark() {
        BenchmarkResult result = new BenchmarkResult("MEMORY_BENCHMARK");
        
        Timer.Sample sample = Timer.start(meterRegistry);
        LocalDateTime startTime = LocalDateTime.now();
        
        try {
            int operationsCount = 100000;
            List<Duration> operationTimes = new ArrayList<>();
            int successCount = 0;
            
            List<byte[]> memoryBlocks = new ArrayList<>();
            
            for (int i = 0; i < operationsCount; i++) {
                LocalDateTime opStart = LocalDateTime.now();
                
                try {
                    // 内存分配和操作
                    byte[] block = new byte[1024]; // 1KB
                    Arrays.fill(block, (byte) (i % 256));
                    memoryBlocks.add(block);
                    
                    // 每1000次操作清理一次内存
                    if (i % 1000 == 0) {
                        memoryBlocks.clear();
                        System.gc();
                    }
                    
                    successCount++;
                    
                    Duration opDuration = Duration.between(opStart, LocalDateTime.now());
                    operationTimes.add(opDuration);
                    
                } catch (Exception e) {
                    log.debug("内存基准测试操作失败: {}", e.getMessage());
                }
            }
            
            Duration totalDuration = Duration.between(startTime, LocalDateTime.now());
            sample.stop(meterRegistry.timer("benchmark.memory.total"));
            
            // 计算统计信息
            calculateBenchmarkStatistics(result, totalDuration, operationsCount, 
                    successCount, operationTimes);
            
            // 记录性能指标
            recordBenchmarkMetrics("memory_benchmark", result);
            
            log.info("内存基准测试完成: 操作数={}, 成功率={:.2f}%, 平均OPS={:.2f}", 
                    operationsCount, result.getSuccessRate(), result.getOperationsPerSecond());
            
        } catch (Exception e) {
            log.error("内存基准测试失败", e);
            sample.stop(meterRegistry.timer("benchmark.memory.error"));
        }
        
        return result;
    }
    
    /**
     * 数据库基准测试
     */
    @Timed(value = "benchmark.database", description = "Database benchmark test")
    public BenchmarkResult runDatabaseBenchmark() {
        BenchmarkResult result = new BenchmarkResult("DATABASE_BENCHMARK");
        
        Timer.Sample sample = Timer.start(meterRegistry);
        LocalDateTime startTime = LocalDateTime.now();
        
        try {
            int operationsCount = 1000;
            List<Duration> operationTimes = new ArrayList<>();
            int successCount = 0;
            
            for (int i = 0; i < operationsCount; i++) {
                LocalDateTime opStart = LocalDateTime.now();
                
                try {
                    // 数据库操作基准测试
                    performDatabaseOperation();
                    successCount++;
                    
                    Duration opDuration = Duration.between(opStart, LocalDateTime.now());
                    operationTimes.add(opDuration);
                    
                } catch (Exception e) {
                    log.debug("数据库基准测试操作失败: {}", e.getMessage());
                }
            }
            
            Duration totalDuration = Duration.between(startTime, LocalDateTime.now());
            sample.stop(meterRegistry.timer("benchmark.database.total"));
            
            // 计算统计信息
            calculateBenchmarkStatistics(result, totalDuration, operationsCount, 
                    successCount, operationTimes);
            
            // 记录性能指标
            recordBenchmarkMetrics("database_benchmark", result);
            
            log.info("数据库基准测试完成: 操作数={}, 成功率={:.2f}%, 平均OPS={:.2f}", 
                    operationsCount, result.getSuccessRate(), result.getOperationsPerSecond());
            
        } catch (Exception e) {
            log.error("数据库基准测试失败", e);
            sample.stop(meterRegistry.timer("benchmark.database.error"));
        }
        
        return result;
    }
    
    /**
     * 缓存基准测试
     */
    @Timed(value = "benchmark.cache", description = "Cache benchmark test")
    public BenchmarkResult runCacheBenchmark() {
        BenchmarkResult result = new BenchmarkResult("CACHE_BENCHMARK");
        
        Timer.Sample sample = Timer.start(meterRegistry);
        LocalDateTime startTime = LocalDateTime.now();
        
        try {
            int operationsCount = 10000;
            List<Duration> operationTimes = new ArrayList<>();
            int successCount = 0;
            int cacheHits = 0;
            
            Map<String, String> testCache = new HashMap<>();
            
            for (int i = 0; i < operationsCount; i++) {
                LocalDateTime opStart = LocalDateTime.now();
                
                try {
                    String key = "test_key_" + (i % 100); // 重复使用100个key
                    
                    if (testCache.containsKey(key)) {
                        // 缓存命中
                        String value = testCache.get(key);
                        cacheHits++;
                    } else {
                        // 缓存未命中，模拟从数据源获取
                        String value = "test_value_" + i;
                        testCache.put(key, value);
                    }
                    
                    successCount++;
                    
                    Duration opDuration = Duration.between(opStart, LocalDateTime.now());
                    operationTimes.add(opDuration);
                    
                } catch (Exception e) {
                    log.debug("缓存基准测试操作失败: {}", e.getMessage());
                }
            }
            
            Duration totalDuration = Duration.between(startTime, LocalDateTime.now());
            sample.stop(meterRegistry.timer("benchmark.cache.total"));
            
            // 计算统计信息
            calculateBenchmarkStatistics(result, totalDuration, operationsCount, 
                    successCount, operationTimes);
            
            // 添加缓存特定指标
            double cacheHitRate = (double) cacheHits / successCount * 100;
            result.getAdditionalMetrics().put("cacheHitRate", cacheHitRate);
            result.getAdditionalMetrics().put("cacheHits", cacheHits);
            result.getAdditionalMetrics().put("cacheMisses", successCount - cacheHits);
            
            // 记录性能指标
            recordBenchmarkMetrics("cache_benchmark", result);
            
            log.info("缓存基准测试完成: 操作数={}, 成功率={:.2f}%, 缓存命中率={:.2f}%", 
                    operationsCount, result.getSuccessRate(), cacheHitRate);
            
        } catch (Exception e) {
            log.error("缓存基准测试失败", e);
            sample.stop(meterRegistry.timer("benchmark.cache.error"));
        }
        
        return result;
    }
    
    /**
     * 网络基准测试
     */
    @Timed(value = "benchmark.network", description = "Network benchmark test")
    public BenchmarkResult runNetworkBenchmark() {
        BenchmarkResult result = new BenchmarkResult("NETWORK_BENCHMARK");
        
        Timer.Sample sample = Timer.start(meterRegistry);
        LocalDateTime startTime = LocalDateTime.now();
        
        try {
            int operationsCount = 1000;
            List<Duration> operationTimes = new ArrayList<>();
            int successCount = 0;
            
            for (int i = 0; i < operationsCount; i++) {
                LocalDateTime opStart = LocalDateTime.now();
                
                try {
                    // 模拟网络操作
                    performNetworkOperation();
                    successCount++;
                    
                    Duration opDuration = Duration.between(opStart, LocalDateTime.now());
                    operationTimes.add(opDuration);
                    
                } catch (Exception e) {
                    log.debug("网络基准测试操作失败: {}", e.getMessage());
                }
            }
            
            Duration totalDuration = Duration.between(startTime, LocalDateTime.now());
            sample.stop(meterRegistry.timer("benchmark.network.total"));
            
            // 计算统计信息
            calculateBenchmarkStatistics(result, totalDuration, operationsCount, 
                    successCount, operationTimes);
            
            // 记录性能指标
            recordBenchmarkMetrics("network_benchmark", result);
            
            log.info("网络基准测试完成: 操作数={}, 成功率={:.2f}%, 平均OPS={:.2f}", 
                    operationsCount, result.getSuccessRate(), result.getOperationsPerSecond());
            
        } catch (Exception e) {
            log.error("网络基准测试失败", e);
            sample.stop(meterRegistry.timer("benchmark.network.error"));
        }
        
        return result;
    }
    
    /**
     * 异步执行完整基准测试套件
     */
    @Async
    public CompletableFuture<Map<String, BenchmarkResult>> runFullBenchmarkSuite() {
        Map<String, BenchmarkResult> results = new HashMap<>();
        
        try {
            log.info("开始执行完整基准测试套件");
            
            results.put("cpu", runCpuBenchmark());
            results.put("memory", runMemoryBenchmark());
            results.put("database", runDatabaseBenchmark());
            results.put("cache", runCacheBenchmark());
            results.put("network", runNetworkBenchmark());
            
            log.info("完整基准测试套件执行完成");
            
        } catch (Exception e) {
            log.error("执行完整基准测试套件失败", e);
        }
        
        return CompletableFuture.completedFuture(results);
    }
    
    /**
     * 执行CPU密集型计算
     */
    private double performCpuIntensiveCalculation() {
        double result = 0.0;
        for (int i = 0; i < 1000; i++) {
            result += Math.sqrt(i) * Math.sin(i) * Math.cos(i);
        }
        return result;
    }
    
    /**
     * 执行数据库操作
     */
    private void performDatabaseOperation() {
        // 模拟数据库操作
        try {
            Thread.sleep(ThreadLocalRandom.current().nextInt(1, 10)); // 1-10ms
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * 执行网络操作
     */
    private void performNetworkOperation() {
        // 模拟网络操作
        try {
            Thread.sleep(ThreadLocalRandom.current().nextInt(10, 50)); // 10-50ms
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    /**
     * 计算基准测试统计信息
     */
    private void calculateBenchmarkStatistics(BenchmarkResult result, Duration totalDuration,
                                            int operationsCount, int successCount,
                                            List<Duration> operationTimes) {
        result.setTotalDuration(totalDuration);
        result.setOperationsCount(operationsCount);
        result.setSuccessRate((double) successCount / operationsCount * 100);
        
        if (totalDuration.toMillis() > 0) {
            result.setOperationsPerSecond((double) successCount / totalDuration.toMillis() * 1000);
        }
        
        if (!operationTimes.isEmpty()) {
            long totalNanos = operationTimes.stream()
                    .mapToLong(Duration::toNanos)
                    .sum();
            result.setAverageOperationTime(Duration.ofNanos(totalNanos / operationTimes.size()));
            
            result.setMinOperationTime(operationTimes.stream()
                    .min(Duration::compareTo)
                    .orElse(Duration.ZERO));
            
            result.setMaxOperationTime(operationTimes.stream()
                    .max(Duration::compareTo)
                    .orElse(Duration.ZERO));
        }
    }
    
    /**
     * 记录基准测试指标
     */
    private void recordBenchmarkMetrics(String benchmarkName, BenchmarkResult result) {
        try {
            // 记录操作数
            performanceMonitoringService.recordMetric(
                    benchmarkName + "_operations_count",
                    MetricType.CUSTOM,
                    BigDecimal.valueOf(result.getOperationsCount()),
                    "count",
                    "benchmark"
            );
            
            // 记录成功率
            performanceMonitoringService.recordMetric(
                    benchmarkName + "_success_rate",
                    MetricType.CUSTOM,
                    BigDecimal.valueOf(result.getSuccessRate()).setScale(2, RoundingMode.HALF_UP),
                    "%",
                    "benchmark"
            );
            
            // 记录每秒操作数
            performanceMonitoringService.recordMetric(
                    benchmarkName + "_ops_per_second",
                    MetricType.THROUGHPUT,
                    BigDecimal.valueOf(result.getOperationsPerSecond()).setScale(2, RoundingMode.HALF_UP),
                    "ops/s",
                    "benchmark"
            );
            
            // 记录平均操作时间
            if (result.getAverageOperationTime() != null) {
                performanceMonitoringService.recordMetric(
                        benchmarkName + "_avg_operation_time",
                        MetricType.RESPONSE_TIME,
                        BigDecimal.valueOf(result.getAverageOperationTime().toMillis()),
                        "ms",
                        "benchmark"
                );
            }
            
        } catch (Exception e) {
            log.error("记录基准测试指标失败: {}", benchmarkName, e);
        }
    }
}